package com.cl.ks.service;

import com.alibaba.fastjson.JSONObject;
import com.cl.ks.entity.*;
import com.cl.ks.enums.TargetType;
import com.cl.ks.repository.*;
import com.cl.ks.utils.QueryDslUtil;
import com.jandar.pile.common.util.IParamBundle;
import com.jandar.pile.common.util.JwtUtil;
import com.jandar.pile.common.util.PageBundle;
import com.jandar.pile.common.util.ParamBundle;
import com.cl.pile.rule.filter.IFilterOperation;
import com.cl.pile.rule.func.IFunc;
import com.cl.pile.rule.process.RuleMatcher;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.java.Log;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.cl.ks.constant.QTableConstant.*;
@Service
@Log
public class KsRuleServiceOld {
    private final RuleMatcher ruleMatcher;
    private final JwtUtil<Long, Long> jwtUtil;
    private final KsRuleRepository ksRuleRepository;
    private final RlRuleTableRepository rlRuleTableRepository;
    private final JPAQueryFactory queryFactory;

    public KsRuleServiceOld(RuleMatcher ruleMatcher,  JwtUtil<Long, Long> jwtUtil, KsRuleRepository ksRuleRepository, RlRuleTableRepository rlRuleTableRepository, JPAQueryFactory queryFactory) {
        this.ruleMatcher = ruleMatcher;
        this.jwtUtil = jwtUtil;
        this.ksRuleRepository = ksRuleRepository;
        this.rlRuleTableRepository = rlRuleTableRepository;
        this.queryFactory = queryFactory;
    }


    public List<String> getKsRuleFields(String ruleExpression) {
        List<String> res = new ArrayList<>();
        String regexPattern = "\"field\": \"(.[^\"]+)\"";
        Pattern pattern = Pattern.compile(regexPattern);
        Matcher matcher = pattern.matcher(ruleExpression);
        while (matcher.find()) {
            res.add(matcher.group(1));
        }
        return res;
    }

    public ResponseEntity<Object> getOps() {
        List<JSONObject> ops = new ArrayList<>();
        for (Map.Entry<String, IFilterOperation> entry : ruleMatcher.getFilterOperationMap().entrySet()) {
            JSONObject item = new JSONObject();
            item.put("name", entry.getValue().filterName());
            item.put("op", entry.getKey());
            ops.add(item);
        }
        return ResponseEntity.ok().body(ops);
    }

    public ResponseEntity<Object> addKsRule(String auth, KsRuleParam ksRuleParam) {


        String systemCode = jwtUtil.getSystemCode(auth);

        KsRule ksRule = new KsRule();
        ksRule.setRuleName(ksRuleParam.getRuleName());
        ksRule.setRuleExpressionJson(ksRuleParam.getRule().toJSONString());
        ksRule.setPower(ksRuleParam.getPower() + ",j_1");
        ksRule.setUserIds("," + ksRuleParam.getUserId() + ",");
        ksRule.setRoleIds(",1," + ksRuleParam.getRoleId() + ",");
        ksRule.setRuleType(ksRuleParam.getRuleType());
        ksRule.setIsForward(ksRuleParam.isForward);
        ksRule.setShowFields(ksRuleParam.getShowFields());
        ksRule.setSystemCode(systemCode);
        ksRule.setDescription(ksRuleParam.getDescription());
        if (StringUtils.isNotBlank(ksRuleParam.getResultPower())) {
            ksRule.setResultPower(ksRuleParam.getResultPower());
        } else {
            ksRule.setResultPower(ksRuleParam.getResultPower() + ",j_1");
        }
        try {
            ksRuleRepository.save(ksRule);
            createRlRuleTable(ksRuleParam.getRlRuleTableList(), ksRule.getId());

        } catch (Exception e) {
            e.printStackTrace();
        }

//            createFilter(auth,ksRuleParam.id);
        return ResponseEntity.ok().body(ksRule.getId());
    }


    @Transactional
    public ResponseEntity<Object> editKsRule(String auth, KsRuleParam ksRuleParam) {
        KsRule ksRule = queryFactory.selectFrom(qKsRule).where(qKsRule.id.eq(ksRuleParam.id)).fetchOne();
        if (ksRule == null) {
            ksRule = new KsRule();
        }
        ksRule.setRuleName(ksRuleParam.getRuleName());
        ksRule.setRuleExpressionJson(ksRuleParam.getRule().toJSONString());
        ksRule.setRuleType(ksRuleParam.getRuleType());
        ksRule.setShowFields(ksRuleParam.getShowFields());
        ksRule.setDescription(ksRuleParam.getDescription());

        ksRuleRepository.save(ksRule);

        queryFactory.delete(qRlRuleTable).where(qRlRuleTable.ruleId.eq(ksRule.getId())).execute();

        createRlRuleTable(ksRuleParam.getRlRuleTableList(), ksRule.getId());
        return ResponseEntity.ok().body("修改成功");
    }


    public ResponseEntity<Object> getKsRuleListNew(String auth, Map<String, Object> param) {
        BooleanExpression hiddenRuleTypeBooleanExpression = qKsRule.isNull().or(qKsRule.isNotNull());
        IParamBundle bundle = ParamBundle.newBundle(param);
        List<String> hiddenRuleTypes = bundle.get("hiddenRuleTypes", new ArrayList<>());
        if (!hiddenRuleTypes.isEmpty()) {
            for (String hiddenRuleType : hiddenRuleTypes) {
                hiddenRuleTypeBooleanExpression = hiddenRuleTypeBooleanExpression.and(Expressions.asString(",").concat(qKsRule.ruleType).concat(",").contains("," + hiddenRuleType + ","));
            }
        }
        List<String> ruleTypes = bundle.get("ruleTypes", new ArrayList<>());
        if (ruleTypes.isEmpty()) {
            ruleTypes.add(bundle.getString("ruleType"));
        }
        if (ruleTypes.contains("全部")) {
            ruleTypes = new ArrayList<>();
            ruleTypes.add("全部");
        }
        BooleanExpression ruleTypeExpression = qKsRule.isNull().or(qKsRule.isNotNull());
        for (String ruleType : ruleTypes) {
            ruleTypeExpression = ruleTypeExpression.and(Expressions.asString(",").concat(qKsRule.ruleType).concat(",").contains("," + ruleType + ","));
        }
        BooleanExpression finalHiddenRuleTypeBooleanExpression = hiddenRuleTypeBooleanExpression;
        PageBundle pageBundle = bundle.getPageBundle();
        String userId = String.valueOf(jwtUtil.getUserId(auth));
        String roleId = String.valueOf(jwtUtil.getRoleId(auth));
        String depId = String.valueOf(jwtUtil.getDepId(auth));
        String name = bundle.getString("name");
        String systemCode = jwtUtil.getSystemCode(auth);
//        String ruleType = bundle.getString("ruleType");
        String[] excludeRuleType = StringUtils.split(bundle.getString("excludeRuleType"), ",");
        String adminArea = bundle.getString("adminArea");
        Long runLastTimeStart = bundle.getLong("runLastTImeStart");
        Long runLastTimeEnd = bundle.getLong("runLastTImeEnd");
        String tableName = bundle.getString("tableName");
        String runLastTimeSort = bundle.getString("runLastTimeSort");
        String adminAreaSort = bundle.getString("adminAreaSort");
        String runCountSort = bundle.getString("runCountSort");
        String ruleNameSort = bundle.getString("ruleNameSort");
        String ruleTypeSort = bundle.getString("ruleTypeSort");
        String dataTypeCode = bundle.getString("dataTypeCode");
        String dataTypeName = bundle.getString("dataTypeName");
        String onlineFlag = bundle.getString("onlineFlag");
        String onlineFlagSort = bundle.getString("onlineFlagSort");

        List<Integer> ruleIdList = bundle.getIntegerList("ruleIdList");

        List<OrderSpecifier<?>> orderFields = new ArrayList<>();

        Map<String, String> params = (Map<String, String>) param.getOrDefault("params", new HashMap<>());
        if (StringUtils.isBlank(ruleTypeSort)) {
            String sort = params.get("ruleTypeSort");
            if (StringUtils.isNotBlank(sort)) {

                if ("asc".equalsIgnoreCase(sort)) {
                    orderFields.add(qKsRule.ruleType.asc());
                } else {
                    orderFields.add(qKsRule.ruleType.desc());
                }
            }
        }
        if (StringUtils.isBlank(ruleNameSort)) {
            String sort = params.get("ruleNameSort");
            if (StringUtils.isNotBlank(sort)) {

                if ("asc".equalsIgnoreCase(sort)) {
                    orderFields.add(qKsRule.ruleName.asc());
                } else {
                    orderFields.add(qKsRule.ruleName.desc());
                }
            }
        }
        if (StringUtils.isBlank(onlineFlagSort)) {
            String sort = params.get("onlineFlagSort");
            if (StringUtils.isNotBlank(sort)) {

                if ("asc".equalsIgnoreCase(sort)) {
                    orderFields.add(qKsRule.onlineFlag.asc());
                } else {
                    orderFields.add(qKsRule.onlineFlag.desc());
                }
            }
        }
        orderFields.add(qKsRule.id.desc());


        BooleanExpression booleanExpression = QueryDslUtil.generatePowerExpression(qKsRule, qKsRule.power, userId, roleId, depId).and(finalHiddenRuleTypeBooleanExpression);

        if (StringUtils.isNotBlank(onlineFlag)) {
            booleanExpression = booleanExpression.and(qKsRule.onlineFlag.eq(Boolean.parseBoolean(onlineFlag)));
        }

        if (!ruleIdList.isEmpty()) {
            booleanExpression = booleanExpression.and(qKsRule.id.in(ruleIdList));
        }
        if (StringUtils.isNotBlank(systemCode)) {
            booleanExpression = booleanExpression.and(qKsRule.systemCode.eq(systemCode).or(qKsRule.systemCode.isNull()));
        }
        if (StringUtils.isNotBlank(name)) {
            booleanExpression = booleanExpression.and(qKsRule.ruleName.contains(name));
        }

        if (excludeRuleType.length > 0) {
            for (String s : excludeRuleType) {
                booleanExpression = booleanExpression.and(Expressions.asString(",").concat(qKsRule.ruleType).concat(",").notLike("%" + "," + s + "," + "%"));
            }
        }
        if (StringUtils.isNotBlank(adminArea)) {
            booleanExpression = booleanExpression.and(qKsRule.adminArea.contains(adminArea));
        }
        if (StringUtils.isNotBlank(tableName)) {
            booleanExpression = booleanExpression.and(qRlRuleTable.tableName.contains(tableName));
        }
        if (!ruleTypes.isEmpty() && !ruleTypes.contains("全部")) {
            booleanExpression = booleanExpression.and(ruleTypeExpression);
        }

        Map<String, Integer> groupsCount = new HashMap<>();

        List<String> ruleTypeList = queryFactory.select(qKsRule.ruleType).from(qKsRule).where(booleanExpression).fetch();

        for (String ruleTypeStr : ruleTypeList) {
            if (ruleTypeStr == null) {
                continue;
            }
            String[] ruleTypeArray;
            if (ruleTypeStr.contains(",")) {
                ruleTypeArray = ruleTypeStr.split(",");
            } else {
                ruleTypeArray = new String[]{ruleTypeStr};
            }
            for (String s : ruleTypeArray) {
                if (s.isEmpty() || hiddenRuleTypes.contains(s)) {
                    continue;
                }
                if (groupsCount.containsKey(s)) {
                    groupsCount.put(s, groupsCount.get(s) + 1);
                } else {
                    groupsCount.put(s, 1);
                }
            }
        }


        List<KsRuleEx> ksRules = queryFactory
                .select(qKsRule).from(qKsRule)
//                .leftJoin(qKsFlowLike).on(qKsFlowLike.targetType.eq(TargetType.KS_RULE.getValue()).and(qKsRule.id.eq(qKsFlowLike.targetId)))
//                .leftJoin(qKsFlowComment).on(qKsFlowComment.targetType.eq(TargetType.KS_RULE.getValue()).and(qKsRule.id.eq(qKsFlowComment.targetId)))
                .where(booleanExpression)
                .offset(pageBundle.getStart())
                .limit(pageBundle.getSize())
                .orderBy(orderFields.toArray(new OrderSpecifier[0]))
                .fetch().stream().map(r -> {
                    KsRuleEx ksRuleEx = new KsRuleEx();
                    BeanUtils.copyProperties(r, ksRuleEx);
                    return ksRuleEx;
                })
                .peek(e -> {

                    Set<String> ruleFields = new HashSet<>();
                    e.setRuleExpressionJsonStr(String.valueOf(e.getRuleExpressionJson()));
                    if (e.getRuleExpressionJsonStr() != null) {
                        Pattern pattern = Pattern.compile("\"field\":\\s*\"(\\w+)\"");
                        Matcher matcher = pattern.matcher(e.getRuleExpressionJsonStr());
                        while (matcher.find()) {
                            ruleFields.add(matcher.group(1));
                        }
                    }
                    e.setRuleFields(new ArrayList<>(ruleFields));
                    if (StringUtils.isBlank(e.getShowFields())) {
                        e.setShowFields(StringUtils.join(e.getRuleFields(), ","));
                    }
                    if (pageBundle.getSize() >= 999) {
                        return;
                    }

                    e.setRuleExpressionJson(null);
                })
                .collect(Collectors.toList());

        Integer count = queryFactory.select(qKsRule.count()).from(qKsRule)
                .where(booleanExpression)
                .groupBy(qKsRule.id)
                .fetch().size();

        JSONObject page = new JSONObject();
        page.put("list", ksRules);
        page.put("page", pageBundle.getPage());
        page.put("size", pageBundle.getSize());
        page.put("count", count);
        page.put("groupsCount", groupsCount);

        return ResponseEntity.ok(Collections.singletonList(page));
    }

    public ResponseEntity<Object> getKsRuleList(String auth, Map<String, Object> param) {
        BooleanExpression hiddenRuleTypeBooleanExpression = qKsRule.isNull().or(qKsRule.isNotNull());
        IParamBundle bundle = ParamBundle.newBundle(param);
        List<String> hiddenRuleTypes = bundle.get("hiddenRuleTypes", new ArrayList<>());
        if (!hiddenRuleTypes.isEmpty()) {
            for (String hiddenRuleType : hiddenRuleTypes) {
                hiddenRuleTypeBooleanExpression = hiddenRuleTypeBooleanExpression.and(Expressions.asString(",").concat(qKsRule.ruleType).concat(",").contains("," + hiddenRuleType + ","));
            }
        }
        List<String> ruleTypes = bundle.get("ruleTypes", new ArrayList<>());
        if (ruleTypes.isEmpty()) {
            ruleTypes.add(bundle.getString("ruleType"));
        }
        if (ruleTypes.contains("全部") || StringUtils.isBlank(bundle.getString("ruleType"))) {
            ruleTypes = new ArrayList<>();
            ruleTypes.add("全部");
        }
        BooleanExpression finalHiddenRuleTypeBooleanExpression = hiddenRuleTypeBooleanExpression;
        return ResponseEntity.ok(ruleTypes.stream().map(ruleType -> {
            PageBundle pageBundle = bundle.getPageBundle();
            String userId = String.valueOf(jwtUtil.getUserId(auth));
            String roleId = String.valueOf(jwtUtil.getRoleId(auth));
            String depId = String.valueOf(jwtUtil.getDepId(auth));
            String name = bundle.getString("name");
            String systemCode = jwtUtil.getSystemCode(auth);
//        String ruleType = bundle.getString("ruleType");
            String[] excludeRuleType = StringUtils.split(bundle.getString("excludeRuleType"), ",");
            String adminArea = bundle.getString("adminArea");
            Long runLastTimeStart = bundle.getLong("runLastTImeStart");
            Long runLastTimeEnd = bundle.getLong("runLastTImeEnd");
            String tableName = bundle.getString("tableName");
            String runLastTimeSort = bundle.getString("runLastTimeSort");
            String adminAreaSort = bundle.getString("adminAreaSort");
            String ruleTypeSort = bundle.getString("ruleTypeSort");
            String ruleNameSort = bundle.getString("ruleNameSort");
            String runCountSort = bundle.getString("runCountSort");
            String dataTypeCode = bundle.getString("dataTypeCode");
            String dataTypeName = bundle.getString("dataTypeName");
            String onlineFlag = bundle.getString("onlineFlag");

            List<OrderSpecifier<?>> orderFields = new ArrayList<>();
            orderFields.add(qKsRule.id.desc());

            Map<String, String> params = (Map<String, String>) param.getOrDefault("params", new HashMap<>());


            if (StringUtils.isBlank(ruleTypeSort)) {
                String sort = params.get("ruleTypeSort");
                if ("asc".equalsIgnoreCase(sort)) {
                    orderFields.add(qKsRule.ruleType.asc());
                } else {
                    orderFields.add(qKsRule.ruleType.desc());
                }
            }
            if (StringUtils.isBlank(ruleNameSort)) {
                String sort = params.get("ruleNameSort");
                if ("asc".equalsIgnoreCase(sort)) {
                    orderFields.add(qKsRule.ruleName.asc());
                } else {
                    orderFields.add(qKsRule.ruleName.desc());
                }
            }


            List<Integer> ruleIdList = bundle.getIntegerList("ruleIdList");

            BooleanExpression booleanExpression = QueryDslUtil.generatePowerExpression(qKsRule, qKsRule.power, userId, roleId, depId).and(finalHiddenRuleTypeBooleanExpression);

            if (StringUtils.isNotBlank(onlineFlag)) {
                booleanExpression = booleanExpression.and(qKsRule.onlineFlag.eq(Boolean.parseBoolean(onlineFlag)));
            }
            if (!ruleIdList.isEmpty()) {
                booleanExpression = booleanExpression.and(qKsRule.id.in(ruleIdList));
            }
            if (StringUtils.isNotBlank(systemCode)) {
                booleanExpression = booleanExpression.and(qKsRule.systemCode.eq(systemCode).or(qKsRule.systemCode.isNull()));
            }
            if (StringUtils.isNotBlank(name)) {
                booleanExpression = booleanExpression.and(qKsRule.ruleName.contains(name));
            }
            if (StringUtils.isNotBlank(ruleType)) {
                if (!ruleType.equals("全部")) {
                    booleanExpression = booleanExpression.and(Expressions.asString(",").concat(qKsRule.ruleType).concat(",").contains("," + ruleType + ","));
                }
            }

            if (excludeRuleType.length > 0) {
                BooleanBuilder booleanBuilder = new BooleanBuilder();
                for (String s : excludeRuleType) {
                    booleanBuilder.and(Expressions.asString(",").concat(qKsRule.ruleType).concat(",").notLike("%" + "," + s + "," + "%"));
                }
                booleanExpression = booleanExpression.and(qKsRule.ruleType.isNull().or(booleanBuilder));
            }
            if (StringUtils.isNotBlank(adminArea)) {
                booleanExpression = booleanExpression.and(qKsRule.adminArea.contains(adminArea));
            }
            if (StringUtils.isNotBlank(tableName)) {
                booleanExpression = booleanExpression.and(qRlRuleTable.tableName.contains(tableName));
            }

            if (StringUtils.isNotBlank(adminAreaSort)) {
                if (adminAreaSort.equals("desc")) {
                    orderFields.add(qKsRule.adminArea.desc());
                } else {
                    orderFields.add(qKsRule.adminArea.asc());
                }
            }
            if (StringUtils.isNotBlank(ruleTypeSort)) {
                if (ruleTypeSort.equals("desc")) {
                    orderFields.add(qKsRule.ruleType.desc());
                } else {
                    orderFields.add(qKsRule.ruleType.asc());
                }
            }

            Map<String, Integer> groupsCount = new HashMap<>();

            List<String> ruleTypeList = queryFactory.select(qKsRule.ruleType).from(qKsRule).where(booleanExpression).fetch();

            for (String ruleTypeStr : ruleTypeList) {
                if (ruleTypeStr == null) {
                    continue;
                }
                String[] ruleTypeArray;
                if (ruleTypeStr.contains(",")) {
                    ruleTypeArray = ruleTypeStr.split(",");
                } else {
                    ruleTypeArray = new String[]{ruleTypeStr};
                }
                for (String s : ruleTypeArray) {
                    if (s.isEmpty() || hiddenRuleTypes.contains(s)) {
                        continue;
                    }
                    if (groupsCount.containsKey(s)) {
                        groupsCount.put(s, groupsCount.get(s) + 1);
                    } else {
                        groupsCount.put(s, 1);
                    }
                }
            }


            List<KsRuleEx> ksRules = queryFactory
                    .select(qKsRule).from(qKsRule)
                    .where(booleanExpression)
                    .offset(pageBundle.getStart())
                    .limit(pageBundle.getSize())
                    .orderBy(orderFields.toArray(new OrderSpecifier[0]))
                    .fetch().stream().map(r -> {
                        KsRuleEx ksRuleEx = new KsRuleEx();
                        BeanUtils.copyProperties(r, ksRuleEx);
                        return ksRuleEx;
                    })
                    .peek(e -> {
                        if (pageBundle.getSize() == 9999) {
                            return;
                        }
                        Set<String> ruleFields = new HashSet<>();
                        e.setRuleExpressionJsonStr(String.valueOf(e.getRuleExpressionJson()));
                        if (e.getRuleExpressionJsonStr() != null) {
                            Pattern pattern = Pattern.compile("\"field\":\\s*\"(\\w+)\"");
                            Matcher matcher = pattern.matcher(e.getRuleExpressionJsonStr());
                            while (matcher.find()) {
                                ruleFields.add(matcher.group(1));
                            }
                        }
                        log.info("ruleId:" + e.getId());
                        List<RlRuleTable> rlRuleTables = rlRuleTableRepository.getRlRuleTablesByRuleId(e.getId());
                        List<String> tableNames = rlRuleTables.stream().map(RlRuleTable::getTableName).collect(Collectors.toList());
                        List<String> tableColumnContents = rlRuleTables.stream().map(r -> r.getTableName() + "." + r.getColumnName() + "." + r.getMatchContent()).collect(Collectors.toList());
                        List<String> tableColumnNoMatchContents = rlRuleTables.stream().map(r -> r.getTableName() + "." + r.getColumnName() + "." + r.getNoMatchContent()).collect(Collectors.toList());
                        log.info("" + e.getId());
                        e.setRuleFields(new ArrayList<>(ruleFields));
                        e.setRlRuleTables(rlRuleTables);
                        e.setTableColumnContents(tableColumnContents);
                        e.setTableColumnNoMatchContents(tableColumnNoMatchContents);
                        e.setTableNames(tableNames);
                        e.setRuleExpressionJson(null);
                    })
                    .collect(Collectors.toList());

            Integer count = queryFactory.select(qKsRule.count()).from(qKsRule)
                    .where(booleanExpression)
                    .groupBy(qKsRule.id)
                    .fetch().size();

            JSONObject page = new JSONObject();
            page.put("list", ksRules);
            page.put("page", pageBundle.getPage());
            page.put("size", pageBundle.getSize());
            page.put("count", count);
            page.put("groupsCount", groupsCount);
            return page;
        }).collect(Collectors.toList()));

    }


    @Transactional
    public ResponseEntity<Object> delKsRule(String auth, Integer id) {
//        JSONObject user = getUserFromRedis(auth);
        long q1 = queryFactory.delete(qKsRule).where(qKsRule.id.eq(id)).execute();
        long q2 = queryFactory.delete(qRlRuleTable).where(qRlRuleTable.ruleId.eq(id)).execute();
        return ResponseEntity.ok().body("删除成功");
    }

    public ResponseEntity<Object> getFunc() {
        List<JSONObject> funcList = new ArrayList<>();
        for (Map.Entry<String, IFunc> entry : ruleMatcher.getFuncMap().entrySet()) {
            JSONObject item = new JSONObject();
            item.put("name", entry.getValue().funcName());
            item.put("func", entry.getKey());
            funcList.add(item);
        }
        return ResponseEntity.ok().body(funcList);
    }

    public ResponseEntity<Object> testFilterData(FilterDataParam filterDataParam) {
        List<KsRule> ruleList = new ArrayList<>();
        if (filterDataParam.ruleIdList != null && !filterDataParam.ruleIdList.isEmpty()) {
            List<KsRule> ksRuleList = queryFactory.selectFrom(qKsRule).where(qKsRule.id.in(filterDataParam.ruleIdList)).fetch();
            ruleList.addAll(ksRuleList);
        }
        if (filterDataParam.ruleId != null) {
            KsRule rule = queryFactory.selectFrom(qKsRule).where(qKsRule.id.eq(filterDataParam.ruleId)).fetchOne();
            if (rule != null) {
                ruleList.add(rule);
            }
        }

        List<String> needFields = new ArrayList<>();
        AtomicBoolean match = new AtomicBoolean(true);
        ruleList.forEach(r -> {
            List<String> ksRuleFields = getKsRuleFields(r.getRuleExpressionJson());
            Set<String> keySet = filterDataParam.data.keySet();
            ksRuleFields.forEach(ksRuleField -> {
                if (!keySet.contains(ksRuleField)) {
                    if (!needFields.contains(ksRuleField)) {
                        needFields.add(ksRuleField);
                    }
                    match.set(false);
                }
            });
        });
        JSONObject res = new JSONObject();

        if (!needFields.isEmpty()) {
            res.put("msg", "缺少字段" + String.join(",", needFields));
        }
        res.put("match", match.get());
        return ResponseEntity.ok(res);
    }

    public ResponseEntity<Object> filterData(FilterDataParam filterDataParam) {
        List<KsRule> ruleList = new ArrayList<>();
        if (filterDataParam.ruleIdList != null && !filterDataParam.ruleIdList.isEmpty()) {
            List<KsRule> ksRuleList = queryFactory.selectFrom(qKsRule).where(qKsRule.id.in(filterDataParam.ruleIdList)).fetch();
            ruleList.addAll(ksRuleList);
        }
        if (filterDataParam.ruleId != null) {
            KsRule rule = queryFactory.selectFrom(qKsRule).where(qKsRule.id.eq(filterDataParam.ruleId)).fetchOne();
            if (rule != null) {
                ruleList.add(rule);
            }
        }

        if (filterDataParam.tableName != null) {
            List<Integer> ruleIdList = queryFactory.select(qRlRuleTable.ruleId).from(qRlRuleTable).where(qRlRuleTable.tableName.eq(filterDataParam.tableName)).fetch();
            List<KsRule> ksRuleList = queryFactory.selectFrom(qKsRule).where(qKsRule.id.in(ruleIdList)).fetch();
            ruleList.addAll(ksRuleList);
        }

        List<String> totalErrorList = new ArrayList<>();
        List<String> totalTipsList = new ArrayList<>();
        List<JSONObject> cpJsonList = new ArrayList<>();
        List<String> descList = new ArrayList<>();
        List<String> ruleNameList = new ArrayList<>();
        AtomicBoolean match = new AtomicBoolean(true);
        ruleList.forEach(r -> {
            if (!r.getRuleExpressionJson().contains("{#")) {
                List<String> errorList = new ArrayList<>();
                List<String> tipsList = new ArrayList<>();
                JSONObject cpJson = new JSONObject();
                boolean thisMatch = RuleMatcher.execMatchRule(new JSONObject(filterDataParam.data), JSONObject.parseObject(r.getRuleExpressionJson()), cpJson, errorList, tipsList);
                if (!thisMatch) {
                    match.set(false);
                }
                totalErrorList.addAll(errorList);
                totalTipsList.addAll(tipsList);
                cpJsonList.add(cpJson);
                descList.add(r.getDescription());
                ruleNameList.add(r.getRuleName() + ":" + thisMatch);
            }

        });

        JSONObject res = new JSONObject();
        res.put("match", match.get());
        res.put("error", totalErrorList);
        res.put("tips", totalTipsList);
        res.put("cpJson", cpJsonList);
        res.put("description", descList);
        res.put("ruleNameList", ruleNameList);
        return ResponseEntity.ok(res);
    }

    public boolean filterData(Integer ruleId, Map<String, Object> data) {
//        log.info("------------------------filterData-tableName: {}", filterDataParam.tableName);
        List<KsRule> ruleList = new ArrayList<>();
        KsRule rule = queryFactory.selectFrom(qKsRule).where(qKsRule.id.eq(ruleId)).fetchOne();
        if (rule != null) {
            ruleList.add(rule);
        }
        for (KsRule ksRule : ruleList) {
            if (!ksRule.getRuleExpressionJson().contains("{#")) {
                List<String> errorList = new ArrayList<>();
                List<String> tipsList = new ArrayList<>();
                JSONObject cpJson = new JSONObject();
                boolean thisMatch = RuleMatcher.execMatchRule(new JSONObject(data), JSONObject.parseObject(ksRule.getRuleExpressionJson()), cpJson, errorList, tipsList);
                if (!thisMatch) {
                    return false;
                }
            }
        }
        return true;
    }

    @Transactional
    public void createRlRuleTable(List<RlRuleTable> rlRuleTableList, Integer ruleId) {
        if (rlRuleTableList == null || rlRuleTableList.isEmpty()) {
            return;
        }
        Integer id = queryFactory.select(qRlRuleTable.id.max()).from(qRlRuleTable).fetchFirst();
        for (RlRuleTable rlRuleTable : rlRuleTableList) {
            rlRuleTable.setId(++id);
            rlRuleTable.setRuleId(ruleId);
            rlRuleTableRepository.save(rlRuleTable);
        }
    }


    @Data
    public static class FilterDataParam {
        private String tableName;
        private Integer ruleId;

        private List<Integer> ruleIdList;
        private Map<String, Object> data;
    }

    @Data
    public static class KsRuleParam {
        private String description;
        private String showFields;
        List<Integer> ruleIdList;
        private List<String> countBy;

        private List<String> groupBy;
        private List<String> joinOn;
        Integer ruleId;
        List<Integer> sysSourceMappingTableIds;
        Integer sysSourceMappingTableId;
        private List<String> dataTypeCodes;
        private String userId;

        private String roleId;

        private JSONObject rule;

        private String ruleName;

        private Integer id;

        private List<String> tableNames = new ArrayList<>();

        private String ruleType;

        private List<RlRuleTable> rlRuleTableList = new ArrayList<>();

        private String power;
        private String resultPower;

        private boolean isForward;
    }

    @EqualsAndHashCode(callSuper = false)
    @Data
    public static class KsRuleEx extends KsRule {

        private Integer ksFlowLikeCount;
        private Integer ksFlowCommentCount;
        private String ruleExpressionJsonStr;
        private List<String> tableNames;
        private List<String> tableColumnContents;
        private List<String> tableColumnNoMatchContents;
        private Integer match;
        private LocalDateTime createTime;
        private List<String> ruleFields;
        private List<RlRuleTable> rlRuleTables;
        private List<String> dataTypeCodes;
    }

}
